﻿using Microsoft.EntityFrameworkCore;

using Tszy.Unlimited.Base.Exceptions;
using Tszy.Unlimited.Base.Features;
using Tszy.Unlimited.Base.Infrastructure.Logging;
using Tszy.Unlimited.Base.Models;
using Tszy.Unlimited.Data.EntityFramework;

namespace Tszy.Unlimited.Data.Features;

/// <summary>
/// 使用 EntityFramework 做为事务。
/// </summary>
/// <typeparam name="TRequest"></typeparam>
/// <typeparam name="TResponse"></typeparam>
public abstract class EntityFrameworkTransactionFunctionFeatureHandler<TRequest, TResponse> : FunctionFeatureHandler<TRequest, TResponse>
    where TRequest : FunctionFeatureRequest<TResponse>
{
    protected readonly IEntityFrameworkContext _context;

    protected EntityFrameworkTransactionFunctionFeatureHandler(IEntityFrameworkContext context, bool transaction = true) : base(transaction)
    {
        _context = context;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    protected override async Task OnHandleAsync(TRequest request, CancellationToken cancellationToken)
    {
        if (transaction)
        {
            using var transaction = await _context.Database.BeginTransactionAsync(cancellationToken);
            await OnExecuteAsync(request, cancellationToken);
            await transaction.CommitAsync(cancellationToken);
        }
        else
        {
            await OnExecuteAsync(request, cancellationToken);
        }
    }

    public override async Task<ResponseResult<TResponse>> Handle(TRequest request, CancellationToken cancellationToken)
    {
        try
        {
            await OnLoadAsync(request, cancellationToken);
            await OnValidateAsync(request, cancellationToken);
            await OnHandleAsync(request, cancellationToken);

            return ResponseResult<TResponse>.Success(response);
        }
        catch (MainApplicationException exception)
        {
            return ResponseResult<TResponse>.Error(exception.Message, response, exception.ErrorCode);
        }
        catch (DbUpdateException exception)
        {
            TszyLogger.Instance.Fatal($"[{GetType().Name}]执行过程中出现异常", exception);

            if (exception.InnerException != null)
                return ResponseResult<TResponse>.Error(exception.InnerException.Message);

            return ResponseResult<TResponse>.Error(exception.Message);
        }
        catch (Exception exception)
        {
            TszyLogger.Instance.Fatal($"[{GetType().Name}]执行过程中出现异常", exception);
            return ResponseResult<TResponse>.Error(exception.Message);
        }
    }
}

public abstract class EntityFrameworkTransactionFunctionRecordFeatureHandler<TRequest, TResponse> : FunctionRecordFeatureHandler<TRequest, TResponse>
    where TRequest : FunctionRecordFeatureRequest<TResponse>
{
    protected readonly IEntityFrameworkContext _context;

    protected EntityFrameworkTransactionFunctionRecordFeatureHandler(IEntityFrameworkContext context, bool transaction = true) : base(transaction)
    {
        _context = context;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    protected override async Task OnHandleAsync(TRequest request, CancellationToken cancellationToken)
    {
        if (transaction)
        {
            using var transaction = await _context.Database.BeginTransactionAsync(cancellationToken);
            await OnExecuteAsync(request, cancellationToken);
            await transaction.CommitAsync(cancellationToken);
        }
        else
        {
            await OnExecuteAsync(request, cancellationToken);
        }
    }

    public override async Task<ResponseResult<TResponse>> Handle(TRequest request, CancellationToken cancellationToken)
    {
        try
        {
            await OnLoadAsync(request, cancellationToken);
            await OnValidateAsync(request, cancellationToken);
            await OnHandleAsync(request, cancellationToken);

            return ResponseResult<TResponse>.Success(response);
        }
        catch (MainApplicationException exception)
        {
            return ResponseResult<TResponse>.Error(exception.Message, response, exception.ErrorCode);
        }
        catch (DbUpdateException exception)
        {
            TszyLogger.Instance.Fatal($"[{GetType().Name}]执行过程中出现异常", exception);

            if (exception.InnerException != null)
                return ResponseResult<TResponse>.Error(exception.InnerException.Message);

            return ResponseResult<TResponse>.Error(exception.Message);
        }
        catch (Exception exception)
        {
            TszyLogger.Instance.Fatal($"[{GetType().Name}]执行过程中出现异常", exception);
            return ResponseResult<TResponse>.Error(exception.Message);
        }
    }
}